package com.server.common.utils.upload;

import cn.hutool.core.util.ArrayUtil;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.server.common.utils.FileUtils;
import com.server.common.utils.SysThreadPool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

@Component
@Slf4j
public class UploadFile {

    @Value("${upload.endpoint}")
    public void setEndpoint(String value){
        endpoint = value;
    }

    @Value("${upload.accessKeyId}")
    public void setAccessKeyId(String value){
        accessKeyId = value;
    }

    @Value("${upload.accessKeySecret}")
    public void setAccessKeySecret(String value){
        accessKeySecret = value;
    }

    @Value("${upload.bucketName}")
    public void setBucketName(String value){
        bucketName = value;
    }

    @Value("${upload.examineUrl}")
    public void setExamineUrl(String value){
        examineUrl = value;
    }

    @Resource
    private SysThreadPool sysThreadPool;

    private static String saveUrl;

    private static String transitionUrl;

    public static String exist;
    public static String exist2;

    public static String fileUrl;
    public static String fileUrl2;

    @Value("${file.saveUrl}")
    public void setSaveUrl(String value){
        saveUrl = value;
    }

    @Value("${file.transitionUrl}")
    public void setTransitionUrl(String value){
        transitionUrl = value;
    }

    @Value("${file.exist}")
    public void setExist(String value){
        exist = value;
    }

    @Value("${file.exist2}")
    public void setExist2(String value){
        exist2 = value;
    }

    @Value("${file.url}")
    public void setFileUrl(String value){
        fileUrl = value;
    }

    @Value("${file.url2}")
    public void setFileUrl2(String value){
        fileUrl2 = value;
    }


    private static SysThreadPool sysThreadPoolStatic;

    @PostConstruct
    private  void init() {
        sysThreadPoolStatic = sysThreadPool;
    }

    public static String examineUrl;

    private static String endpoint;

    private static String accessKeyId;

    private static String accessKeySecret;

    private static String bucketName;

    static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

    public static String uploadFile(MultipartFile multipartFile){
        if (multipartFile == null){
            log.info("multipartFile cat`t be null");
            throw new RuntimeException("multipartFile cat`t be null");
        }
        String[] split = multipartFile.getOriginalFilename().split("\\.");
        if (ArrayUtil.isAllEmpty(split)){
            log.info("fileName is null");
            throw new RuntimeException("fileName cat`t be null");
        }
        String objectName;
        String fileSuffix = split[split.length - 1];
        if ("PDF".equalsIgnoreCase(fileSuffix)||
                "GIF".equalsIgnoreCase(fileSuffix)||
                "PNG".equalsIgnoreCase(fileSuffix)||
                "JPEG".equalsIgnoreCase(fileSuffix)||
                "JPG".equalsIgnoreCase(fileSuffix)||
                "BMP".equalsIgnoreCase(fileSuffix)
        ){
            objectName =formatter.format(new Date())+"/Image/";
        }else if ("AVI".equalsIgnoreCase(fileSuffix)||
                "MOV".equalsIgnoreCase(fileSuffix)||
                "QT".equalsIgnoreCase(fileSuffix)||
                "ASF".equalsIgnoreCase(fileSuffix)||
                "RM".equalsIgnoreCase(fileSuffix)||
                "NAVI".equalsIgnoreCase(fileSuffix)||
                "DivX".equalsIgnoreCase(fileSuffix)||
                "MPEG".equalsIgnoreCase(fileSuffix)||
                "MPG".equalsIgnoreCase(fileSuffix)
        ){
            objectName = formatter.format(new Date())+"/Video/";
        }else{
            objectName = formatter.format(new Date())+"/Unknown/";
        }
        if (split.length >= 2){
            objectName+= UUID.randomUUID().toString()+"."+fileSuffix;
        }else{
            objectName+= multipartFile.getOriginalFilename();
        }
        // 填写本地文件的完整路径，例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径，则默认从示例程序所属项目对应本地路径中上传文件。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, multipartFile.getInputStream());
            // 如果需要上传时设置存储类型和访问权限，请参考以下示例代码。
            // ObjectMetadata metadata = new ObjectMetadata();
            // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
            // metadata.setObjectAcl(CannedAccessControlList.Private);
            // putObjectRequest.setMetadata(metadata);

            // 上传文件。
            ossClient.putObject(putObjectRequest);
            return examineUrl+"/"+objectName;
        } catch (OSSException oe) {
            log.info("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            log.info("Error Message:" + oe.getErrorMessage());
            log.info("Error Code:" + oe.getErrorCode());
            log.info("Request ID:" + oe.getRequestId());
            log.info("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            log.info("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.info("Error Message:" + ce.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        throw new RuntimeException("file upload failure");

    }
    public static String uploadVideo(MultipartFile multipartFile){
        if (multipartFile == null){
            log.info("multipartFile cat`t be null");
            throw new RuntimeException("multipartFile cat`t be null");
        }

        String[] split = multipartFile.getOriginalFilename().split("\\.");
        if (ArrayUtil.isAllEmpty(split)){
            log.info("fileName is null");
            throw new RuntimeException("fileName cat`t be null");
        }
        String objectName;
        String fileSuffix = split[split.length - 1];
        String s = FileUtils.saveMultipartFile(multipartFile, saveUrl);
        if ("PDF".equalsIgnoreCase(fileSuffix)||
                "GIF".equalsIgnoreCase(fileSuffix)||
                "PNG".equalsIgnoreCase(fileSuffix)||
                "JPEG".equalsIgnoreCase(fileSuffix)||
                "JPG".equalsIgnoreCase(fileSuffix)||
                "BMP".equalsIgnoreCase(fileSuffix)
        ){
            objectName = formatter.format(new Date())+"/Image/";
        }else if ("AVI".equalsIgnoreCase(fileSuffix)||
                "MOV".equalsIgnoreCase(fileSuffix)||
                "QT".equalsIgnoreCase(fileSuffix)||
                "ASF".equalsIgnoreCase(fileSuffix)||
                "RM".equalsIgnoreCase(fileSuffix)||
                "NAVI".equalsIgnoreCase(fileSuffix)||
                "DivX".equalsIgnoreCase(fileSuffix)||
                "MPEG".equalsIgnoreCase(fileSuffix)||
                "MPG".equalsIgnoreCase(fileSuffix)
        ){
            objectName = formatter.format(new Date())+"/Video/";
        }else{
            objectName = formatter.format(new Date())+"/Unknown/";
        }
        if (split.length >= 2){
            objectName+= UUID.randomUUID().toString()+"."+fileSuffix;
        }else{
            objectName+= multipartFile.getOriginalFilename();
        }
        // 填写本地文件的完整路径，例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径，则默认从示例程序所属项目对应本地路径中上传文件。
        return   uploadFile(objectName, new File(s));

    }
    public static String uploadFile(String objectName, File file){
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, file);
            // 如果需要上传时设置存储类型和访问权限，请参考以下示例代码。
            // ObjectMetadata metadata = new ObjectMetadata();
            // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
            // metadata.setObjectAcl(CannedAccessControlList.Private);
            // putObjectRequest.setMetadata(metadata);

            // 上传文件。
            ossClient.putObject(putObjectRequest);

            return examineUrl+"/"+objectName;
        } catch (OSSException oe) {
            log.info("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            log.info("Error Message:" + oe.getErrorMessage());
            log.info("Error Code:" + oe.getErrorCode());
            log.info("Request ID:" + oe.getRequestId());
            log.info("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            log.info("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.info("Error Message:" + ce.getMessage());
        } finally {
            file.delete();
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        throw new RuntimeException("file upload failure");
    }
    public static String uploadFile(MultipartFile multipartFile,String fileName){
        if (multipartFile == null){
            log.info("multipartFile cat`t be null");
            throw new RuntimeException("multipartFile cat`t be null");
        }
        String[] split = multipartFile.getOriginalFilename().split("\\.");
        if (ArrayUtil.isAllEmpty(split)){
            log.info("fileName is null");
            throw new RuntimeException("fileName cat`t be null");
        }
        String objectName;
        String fileSuffix = split[split.length - 1];
        if ("PDF".equalsIgnoreCase(fileSuffix)||
                "GIF".equalsIgnoreCase(fileSuffix)||
                "PNG".equalsIgnoreCase(fileSuffix)||
                "JPEG".equalsIgnoreCase(fileSuffix)||
                "JPG".equalsIgnoreCase(fileSuffix)||
                "BMP".equalsIgnoreCase(fileSuffix)
        ){
            objectName = "Image/";
        }else if ("AVI".equalsIgnoreCase(fileSuffix)||
                "MOV".equalsIgnoreCase(fileSuffix)||
                "QT".equalsIgnoreCase(fileSuffix)||
                "ASF".equalsIgnoreCase(fileSuffix)||
                "RM".equalsIgnoreCase(fileSuffix)||
                "NAVI".equalsIgnoreCase(fileSuffix)||
                "DivX".equalsIgnoreCase(fileSuffix)||
                "MPEG".equalsIgnoreCase(fileSuffix)||
                "MPG".equalsIgnoreCase(fileSuffix)
        ){
            objectName = "Video/";
        }else{
            objectName = "Unknown/";
        }
        if (split.length >= 2){
            objectName+= fileName+"."+fileSuffix;
        }else{
            objectName+= multipartFile.getOriginalFilename();
        }
        // 填写本地文件的完整路径，例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径，则默认从示例程序所属项目对应本地路径中上传文件。

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, multipartFile.getInputStream());
            // 如果需要上传时设置存储类型和访问权限，请参考以下示例代码。
            // ObjectMetadata metadata = new ObjectMetadata();
            // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
            // metadata.setObjectAcl(CannedAccessControlList.Private);
            // putObjectRequest.setMetadata(metadata);

            // 上传文件。
            ossClient.putObject(putObjectRequest);
            return examineUrl+"/"+objectName;
        } catch (OSSException oe) {
            log.info("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            log.info("Error Message:" + oe.getErrorMessage());
            log.info("Error Code:" + oe.getErrorCode());
            log.info("Request ID:" + oe.getRequestId());
            log.info("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            log.info("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.info("Error Message:" + ce.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        throw new RuntimeException("file upload failure");
    }
}
